package cc.linker.steplink.crm.task;

import cc.linker.steplink.crm.commons.Constants;
import cc.linker.steplink.crm.commons.RandomCodeGenerator;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.lock.RedisLock;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.dao.*;
import cc.linker.steplink.crm.domain.Fans;
import cc.linker.steplink.crm.domain.FansList;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @Description: 同步公众号用户数据
 * @Author: wuyue
 * @Date: 2019/9/5 17:25
 * @Version: v1.8.3
 */
@Slf4j
@Component
public class SyncPublicUserDataTask {

    private static final String URL_SUFFIX = "Export.php?m=Home&c=Export&action=get_fans_list";
    private static final String CONF_NAME = "LastSyncTime4Fans";
    private static final String CONF_DESC = "公众号粉丝上次同步时间";
    private static final Integer REQUEST_COUNT_PER_DAY = -1;
    private static final Integer PAGE_SIZE = 300;
    private static final Long SLEEP_TIME = 1000L;

    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private HttpService httpService;
    @Autowired
    private SyncDao syncDao;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private CustomerDao customerDao;
    @Autowired
    private CustomerInfoDao customerInfoDao;
    @Autowired
    private CustomerInfoWxDao customerInfoWxDao;
    @Autowired
    private PersonalDao personalDao;
    @Autowired
    private CustomerBindDao customerBindDao;

    /**
     * @Description: 同步粉丝数据, 该接口仅20:00-8:00可调用
     * @Param: 见FansList.class
     * @Return: void
     * @Author: wuyue
     * @Date: 2019/9/6 13:50
     * @Version: v1.8.3
     */
    @Async
    @RedisLock("SyncPublicUserDataTask")
    @Scheduled(cron = "0 0 23 */1 * ?")
    public void syncPublicUserDataTask() {
        this.doSync(null);
    }

    /**
     * @param specifyOrgId 指定机构id
     */
    public void doSync(String specifyOrgId) {
        String url = systemProperties.getWxMatrix() + URL_SUFFIX;
        Map<String, Object> requestMap = new HashMap<>();
        requestMap.put("pageSize", PAGE_SIZE);
        // 列表token,orgId,confValue
        List<Map<String, Object>> tokenList = syncDao.getTokenList(CONF_NAME, specifyOrgId);
        for (Map<String, Object> pub : tokenList) {
            String orgId = (String) pub.get("orgId");
            String token = (String) pub.get("token");
            String updateTime = (String) pub.get("confValue");
            if (StringUtils.isEmpty(updateTime)) {
                // 机构从未设置过更新时间,先设置为0
                updateTime = "0";
            }
            requestMap.put("updateTime", updateTime);
            requestMap.put("public_list", token);
            // 请求次数,初始为1(最少请求1次,看看有没有数据)
            int requestCount = 1;
            // 循环请求
            for (int i = 0; i < requestCount; i++) {
                requestMap.put("pageIndex", i);
                String result;
                try {
                    result = httpService.doPost(url, requestMap);
                } catch (Exception e) {
                    LOGGER.error("矩阵请求发生异常,Matrix request exception", e);
                    break;
                }
                // 结果
                FansList fansList;
                try {
                    fansList = JSON.parseObject(result, FansList.class);
                } catch (Exception e) {
                    LOGGER.error("矩阵结果转为对象异常", e);
                    break;
                }
                if (!StringUtils.isEmpty(fansList.getErrmsg())) {
                    // 返回结果错误
                    LOGGER.error(orgId+"_fansList.getErrmsg" + fansList.getErrmsg());
                    break;
                }
                if (fansList.getDataSource() == null || fansList.getTotalCount() <= 0) {
                    // 没数据
                    LOGGER.info(orgId+"_fansList.getTotalCount <= 0");
                    break;
                }
                // 有数据
                if (i == 0) {
                    // 总记录条数/每次请求条数(可能带小数)
                    double v = fansList.getTotalCount().doubleValue() / PAGE_SIZE.doubleValue();
                    // 请求次数(向上取整)
                    requestCount = (int) Math.ceil(v);
                    if (requestCount > REQUEST_COUNT_PER_DAY && REQUEST_COUNT_PER_DAY != -1) {
                        requestCount = REQUEST_COUNT_PER_DAY;
                    }
                }
                List<Fans> fans = fansList.getDataSource();
                Iterator<Fans> it = fans.iterator();
                while (it.hasNext()) {
                    Fans fan = it.next();
                    fan.setOrgId(orgId);
                    // fan对象入customer、info、wx库(根据openid+token判断重复)
                    this.preserveFans(fan);
                    if (!it.hasNext()) {
                        // 记录最后一条数据的InteractionTime
                        updateTime = fan.getInteractionTime();
                    }
                }
                try {
                    Thread.sleep(SLEEP_TIME);
                } catch (InterruptedException ignored) {

                }
            }
            // 更新机构配置表
            Map<String, Object> param = new HashMap<>();
            param.put("orgId", orgId);
            param.put("name", CONF_NAME);
            param.put("desc", CONF_DESC);
            param.put("value", updateTime);
            sysConfigDao.addOrUpdateConf(param);
        }
    }

    // 因为要根据openid+token判断重复,目前openid有为空状态(未关注),所以暂时没办法用openid+token的唯一索引去做批量插入
    private void preserveFans(Fans fans) {
        if (StringUtils.isEmpty(fans.getUid()) || StringUtils.isEmpty(fans.getSourceID()) || StringUtils.isEmpty(fans.getUserName())) {
            LOGGER.warn("用户信息不完整");
            return;
        }
        String orgId = customerBindDao.getOrgIdFromWeixinList(fans.getSourceID());
        String customerId = personalDao.getCustomerIdByOpenIdAndOrgId(fans.getUid(), orgId);
        if (StringUtils.isEmpty(customerId)) {
            customerId = RandomCodeGenerator.getCustomerId(Constants.CUSTOMER_CODE_SOURCE_WX);
            fans.setCustomerId(customerId);
            fans.setCustomerInfoId(UUID.randomUUID().toString());
            // 不存在则入库
            try {
                customerDao.insertCustomerByFans(fans);
                String area = fans.getCountry() + "@" + fans.getProvince() + "@" + fans.getCity();
                fans.setAddress(area);
                customerInfoDao.insertCustomerByFans(fans);
                customerInfoWxDao.insertCustomerByFans(fans);
            } catch (Exception e) {
                LOGGER.error("同步用户失败", e);
            }
        }
    }


}
